{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#01 RGB\n",
    "import cv2\n",
    "\n",
    "def BGR2RGB(img):\n",
    "    r = img[:, :, 2].copy()\n",
    "    g = img[:, :, 1].copy()\n",
    "    b = img[:, :, 0].copy()\n",
    "\n",
    "    img[:,:,0] = r\n",
    "    img[:,:,1] = g\n",
    "    img[:,:,2] = b\n",
    "\n",
    "    return img\n",
    "\n",
    "img = cv2.imread(\"imori.jpg\")\n",
    "img = BGR2RGB(img)\n",
    "\n",
    "# Save result\n",
    "cv2.imwrite(\"out_rgb.jpg\", img)\n",
    "# cv2.imshow(\"result\", img)\n",
    "# cv2.waitKey(0)\n",
    "# cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#02 GrayScale\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "# astype 类型转换\n",
    "def grayscale(img):\n",
    "    b = img[:,:,0].copy()\n",
    "    g = img[:,:,1].copy()\n",
    "    r = img[:,:,2].copy()\n",
    "\n",
    "    y = 0.2126*r + 0.7152*g + 0.0722*b #浮点运算，读取Img时转换成浮点类型\n",
    "\n",
    "    y = y.astype(np.uint8)\n",
    "\n",
    "    return y\n",
    "\n",
    "img = cv2.imread(\"imori.jpg\")\n",
    "gray = grayscale(img)\n",
    "cv2.imwrite(\"out_gray.jpg\",gray)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'<' not supported between instances of 'NoneType' and 'int'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_54072/632140175.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0mimg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcv2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimread\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"out2.jpg\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbinarization\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimg\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m128\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m \u001b[0mcv2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"out_binarization.jpg\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/tmp/ipykernel_54072/632140175.py\u001b[0m in \u001b[0;36mbinarization\u001b[0;34m(img, th)\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;31m# 二值化\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mbinarization\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimg\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m128\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m     \u001b[0mimg\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mimg\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mth\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      8\u001b[0m     \u001b[0mimg\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mimg\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mth\u001b[0m \u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m255\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mimg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: '<' not supported between instances of 'NoneType' and 'int'"
     ]
    }
   ],
   "source": [
    "#03 Binarization\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "# 二值化\n",
    "def binarization(img,th=128):\n",
    "    img[img < th] = 0\n",
    "    img[img >= th ] = 255\n",
    "    return img \n",
    "\n",
    "img = cv2.imread(\"out2.jpg\")\n",
    "t = binarization(img,th=128)\n",
    "cv2.imwrite(\"out_binarization.jpg\",t)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#04 Otsu's Method\n",
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "def otsu_binarization(gray_img):\n",
    "    #最大类间方差算法\n",
    "    max_t = 0\n",
    "    max_sigma = 0\n",
    "    H,W,_ = gray_img.shape\n",
    "\n",
    "    for _t in range(1, 255):\n",
    "        c0 = gray_img[np.where(gray_img < _t)]\n",
    "        c1 = gray_img[np.where(gray_img >= _t)]\n",
    "\n",
    "        w0 = len(c0)/(H*W)\n",
    "        w1 = len(c1)/(H*W)\n",
    "\n",
    "        m0 = np.mean(c0) if len(c0) > 0 else 0\n",
    "        m1 = np.mean(c1) if len(c1) > 0 else 0\n",
    "\n",
    "        sigma = w0*w1 *((m0-m1)**2)\n",
    "        if sigma > max_sigma:\n",
    "            max_sigma = sigma\n",
    "            max_t = _t\n",
    "\n",
    "    print(\"threshold >>\", max_t)\n",
    "    th = max_t\n",
    "    gray_img[gray_img < th] = 0\n",
    "    gray_img[gray_img >= th] = 255\n",
    "\n",
    "    return gray_img\n",
    "\n",
    "img = cv2.imread(\"out_gray.jpg\")\n",
    "out = otsu_binarization(img)\n",
    "cv2.imwrite(\"out_otsu.jpg\",out)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#05 HSV变换\n",
    "import cv2 \n",
    "import numpy as np\n",
    "\n",
    "def BGR2HSV(_img):\n",
    "    #RGB的取值范围为0到1\n",
    "    img = _img.copy() / 255.\n",
    "\n",
    "    hsv = np.zeros_like(img,dtype = np.float32)\n",
    "\n",
    "    #取RGB中最大的,min_arg找到最小的那一维\n",
    "    max_v = np.max(img, axis=2).copy()\n",
    "    min_v = np.min(img, axis=2).copy()\n",
    "    min_arg = np.argmin(img, axis=2)\n",
    "\n",
    "    #H\n",
    "    hsv[...,0][np.where(max_v == min_v)] = 0\n",
    "    ## Min=B\n",
    "    #np.where返回满足条件的坐标\n",
    "    ind = np.where(min_v == 0)\n",
    "    hsv[...,0][ind] = 60 * (img[...,1][ind]-img[...,2][ind]) / (max_v[ind]-min_v[ind]) + 60\n",
    "    ## Min=R\n",
    "    ind = np.where(min_v == 2)\n",
    "    hsv[...,0][ind] = 60 * (img[...,0][ind]-img[...,1][ind]) / (max_v[ind]-min_v[ind]) + 180\n",
    "    ## Min=G\n",
    "    ind = np.where(min_v == 1)\n",
    "    hsv[...,0][ind] = 60 * (img[...,2][ind]-img[...,0][ind]) / (max_v[ind]-min_v[ind]) + 300\n",
    "\n",
    "    #S\n",
    "    hsv[...,1] = max_v.copy() - min_v.copy()\n",
    "\n",
    "    #V\n",
    "    hsv[...,2] = max_v.copy()\n",
    "\n",
    "    return hsv\n",
    "\n",
    "def HSV2BGR(_img,hsv):\n",
    "    img =_img.copy() / 255.\n",
    "\n",
    "    max_v = np.max(img, axis=2).copy()\n",
    "    min_v = np.min(img, axis =2).copy()\n",
    "\n",
    "    out = np.zeros_like(img)\n",
    "\n",
    "    H = hsv[...,0]\n",
    "    S = hsv[...,1]\n",
    "    V = hsv[...,2]\n",
    "   \n",
    "    C = S\n",
    "    H_ = H/60.\n",
    "    X = C * (1 - np.abs( H_%2 - 1))\n",
    "    Z = np.zeros_like(H)\n",
    "\n",
    "    vals = [[Z,X,C], [Z,C,X], [X,C,Z], [C,X,Z], [C,Z,X], [X,Z,C]]\n",
    "\n",
    "    for i in range(6):\n",
    "        ind = np.where((i <= H_) & (H_ < (i+1)))\n",
    "        out[...,0][ind] = (V - C)[ind] + vals[i][0][ind]\n",
    "        out[...,1][ind] = (V - C)[ind] + vals[i][1][ind]\n",
    "        out[...,2][ind] = (V - C)[ind] + vals[i][2][ind]\n",
    "    out[np.where(max_v == min_v)] = 0\n",
    "    out = np.clip(out, 0 , 1)\n",
    "    out = (out * 255).astype(np.uint8)\n",
    "\n",
    "    return out\n",
    "\n",
    "img = cv2.imread(\"imori.jpg\").astype(np.float32)\n",
    "\n",
    "# RGB > HSV\n",
    "hsv = BGR2HSV(img)\n",
    "\n",
    "# 将色相反转，再用RGB\n",
    "# Transpose Hue\n",
    "hsv[..., 0] = (hsv[..., 0] + 180) % 360\n",
    "\n",
    "# HSV > RGB\n",
    "out = HSV2BGR(img, hsv)\n",
    "\n",
    "# Save result\n",
    "cv2.imwrite(\"out_hsvrgb.jpg\", hsv)\n",
    "cv2.imshow(\"result\", hsv)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "a02fc57d4bb34e54cb9d8bcb11aaa4ee4841d81f90f60f7211ebef67eb3f22c7"
  },
  "kernelspec": {
   "display_name": "Python 3.6.13 64-bit ('torch': conda)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.13"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
